﻿using AutoMapper;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Zocono.Infrastructure.Common;
using Zocono.WCS.Domain.DomainRepository;
using Zocono.WCS.Domain.EntityInfo;
using Zocono.WCS.Infrastructure.ApllicationDto.WCSTaskDto;
using Zocono.WCS.Infrastructure.ApllicationDto;
using Zocono.WCS.Infrastructure.ApllicationDto.DtoWcsManage;

namespace Zocono.WCS.Domain.PlcConnectionDomain
{
    public class PlcConnectionInfoService : IPlcConnectionInfoService
    {
        private readonly ILogUtil _logUtil;
        private readonly ISnowflake _Snowflake;
        private readonly IMapper _Mapper;
        private readonly IPlcConnectionInfoRepository _IPlcConnectionInfoRepository;
        private readonly IPlcConnectionStateInfoRepository _IPlcConnectionStateInfoRepository;
        private readonly IPlcConnectionLockInfoRepository _IPlcConnectionLockInfoRepository;

        public PlcConnectionInfoService(IPlcConnectionInfoRepository plcConnectionInfoRepository
            , ILogUtil logUtil
            , ISnowflake snowflake
            , IMapper mapper, IPlcConnectionStateInfoRepository IPlcConnectionStateInfoRepository, IPlcConnectionLockInfoRepository IPlcConnectionLockInfoRepository)
        {
            _IPlcConnectionInfoRepository = plcConnectionInfoRepository;
            _logUtil = logUtil;
            _Snowflake = snowflake;
            _Mapper = mapper;
            _IPlcConnectionStateInfoRepository = IPlcConnectionStateInfoRepository;
            _IPlcConnectionLockInfoRepository = IPlcConnectionLockInfoRepository;
        }

        public async Task<bool> CreatePlcConnectionInfoAsync(PlcConnectionInfo plcConnectionInfo)
        {
            plcConnectionInfo.ID = _Snowflake.GetId();
            bool isOk = await _IPlcConnectionInfoRepository.InsertAsync(plcConnectionInfo);

            return isOk;
        }

        public async Task<bool> DeletePlcConnectionInfoAsync(List<PlcConnectionInfo> plcConnectionInfoList)
        {
            try
            {
                _IPlcConnectionInfoRepository.AsTenant().BeginTran();

                foreach (var item in plcConnectionInfoList)
                {
                    await _IPlcConnectionInfoRepository.DeleteByIdAsync(item.ID);
                }

                _IPlcConnectionInfoRepository.AsTenant().CommitTran();

                return true;
            }
            catch (Exception ex)
            {
                _IPlcConnectionInfoRepository.AsTenant().RollbackTran();

                throw new Exception(ex.Message);
            }
        }

        public async Task<PageDto<PlcConnectionInfo>> GetPagedPlcConnectionInfoAsync(QueryPlcConnectionInfoDto queryPlcConnectionInfo)
        {
            var exp = Expressionable.Create<PlcConnectionInfo>();
            exp.AndIF(!string.IsNullOrEmpty(queryPlcConnectionInfo.Ip), it => it.IP.Contains(queryPlcConnectionInfo.Ip));
            exp.AndIF(queryPlcConnectionInfo.CpuType.HasValue, it => (int)it.PlcCpuType == queryPlcConnectionInfo.CpuType);
            exp.AndIF(queryPlcConnectionInfo.IsSc.HasValue, it => it.IsSc == queryPlcConnectionInfo.IsSc);
            exp.AndIF(!string.IsNullOrEmpty(queryPlcConnectionInfo.ScEquipmentCode), it => it.ScEquipmentCode.ToString().Contains(queryPlcConnectionInfo.ScEquipmentCode));

            PageDto<PlcConnectionInfo> pagedData = new PageDto<PlcConnectionInfo>();
            RefAsync<int> totalCount = 0;

            var result = await _IPlcConnectionInfoRepository.AsSugarClient().Queryable<PlcConnectionInfo>()
                .Where(exp.ToExpression())
                .ToPageListAsync(queryPlcConnectionInfo.PageIndex, queryPlcConnectionInfo.PageSize, totalCount);

            pagedData.Result = result;
            pagedData.Total = totalCount;

            return pagedData;
        }

        public async Task<bool> ModifyPlcConnectionInfoAsync(PlcConnectionInfo plcConnectionInfo)
        {
            bool isOk = await _IPlcConnectionInfoRepository.UpdateAsync(
                p => new PlcConnectionInfo
                {
                    IP = plcConnectionInfo.IP,
                    PlcCpuType = plcConnectionInfo.PlcCpuType,
                    Rack = plcConnectionInfo.Rack,
                    Slot = plcConnectionInfo.Slot,
                    IsSc = plcConnectionInfo.IsSc,
                    ScEquipmentCode = plcConnectionInfo.ScEquipmentCode
                },
                p => p.ID == plcConnectionInfo.ID);

            return isOk;
        }

        #region plc连接锁定与状态相关
        public async Task<List<PlcConnectionLockInfoDto>> GetPlcConnectionLockInfoAsync(QueryPlcConnectionLockInfoDto queryPlcConnectionLockInfoDto)
        {
            var plcConnectionID = queryPlcConnectionLockInfoDto.PlcConnectionID;
            var programeCode = queryPlcConnectionLockInfoDto.ProgrameCode;
            var jobName = queryPlcConnectionLockInfoDto.JobName;
            var isLock = queryPlcConnectionLockInfoDto.IsLock;
            var exp = Expressionable.Create<PlcConnectionLockInfo, PlcConnectionInfo>();
            exp.AndIF(plcConnectionID.HasValue && plcConnectionID != 0, (a, b) => a.PlcConnectionID == plcConnectionID);
            exp.AndIF(!string.IsNullOrEmpty(programeCode), (a, b) => a.ProgrameCode.Contains(programeCode));
            exp.AndIF(!string.IsNullOrEmpty(jobName), (a, b) => a.JobName.Contains(jobName));
            exp.AndIF(isLock.HasValue, (a, b) => a.IsLock == isLock);

            var list = await _IPlcConnectionLockInfoRepository.GetPlcConnectionLockInfoAsync(exp.ToExpression());

            return list;
        }

        public async Task<List<PlcConnectionStateInfoDto>> GetPlcConnectionStateInfoAsync(QueryPlcConnectionStateInfoDto queryPlcConnectionStateInfoDto)
        {
            var plcConnectionID = queryPlcConnectionStateInfoDto.PlcConnectionID;
            var programeCode = queryPlcConnectionStateInfoDto.ProgrameCode;
            var connected = queryPlcConnectionStateInfoDto.Connected;
            var exp = Expressionable.Create<PlcConnectionStateInfo, PlcConnectionInfo>();
            exp.AndIF(plcConnectionID.HasValue && plcConnectionID != 0, (a, b) => a.PlcConnectionID == plcConnectionID);
            exp.AndIF(!string.IsNullOrEmpty(programeCode), (a, b) => a.ProgrameCode.Contains(programeCode));
            exp.AndIF(connected.HasValue, (a, b) => a.Connected == connected);
            
            var list = await _IPlcConnectionStateInfoRepository.GetPlcConnectionStateInfoAsync(exp.ToExpression());

            return list;
        }

        public async Task<List<PlcConnectionInfo>> GetPlcConnectionInfoAsync()
        {
            var res =await _IPlcConnectionInfoRepository.GetListAsync();
            return res;
        }

        public async Task<PlcConnectionInfo> GetPlcConnectionInfoByIdAsync(long id)
        {
            var res = await _IPlcConnectionInfoRepository.GetByIdAsync(id);
            return res;
        }
        
        public async Task<PlcConnectionInfo> GetPlcConnectionInfoByIpAsync(string ip)
        {
            var res = await _IPlcConnectionInfoRepository.GetFirstAsync(it => it.IP == ip);
            return res;
        }
        public async Task<bool> DeletePlcConnectionIndoByIdAsync(long id)
        {
            var res = await _IPlcConnectionInfoRepository.DeleteByIdAsync(id);
            return res;
        }
        #endregion
    }
}
